#include "touch.h"
#include "lcd.h"
#include "stdio.h"

// 0.065178,0.081455,120,160,2153,2123

static double linear_kx = 0;
static double linear_ky = 0;
static uint16_t xc = 0;
static uint16_t yc = 0;
static uint16_t xlc = 0;
static uint16_t ylc = 0;

void delay_us(uint32_t value)
{
    uint32_t clk = 72;
    uint32_t temp = 0;
    while (value--)
    {
        temp = clk;
        while (temp--)
        {
            __NOP();
        }
    }
}

void t_cs(uint8_t value)
{
    HAL_GPIO_WritePin(T_CS_GPIO_Port, T_CS_Pin, value);
}

void t_sck(uint8_t value)
{
    HAL_GPIO_WritePin(T_SCK_GPIO_Port, T_SCK_Pin, value);
}

void t_mosi(uint8_t value)
{
    HAL_GPIO_WritePin(T_MOSI_GPIO_Port, T_MOSI_Pin, value);
}

uint8_t t_miso()
{
    return HAL_GPIO_ReadPin(T_MISO_GPIO_Port, T_MISO_Pin);
}

void t_pen(uint8_t value)
{
    HAL_GPIO_WritePin(T_PEN_GPIO_Port, T_PEN_Pin, value);
}

uint16_t t_write_and_read_ad(uint8_t command)
{
    uint16_t data = 0;
    /*开始状态*/
    t_sck(0);
    t_mosi(0);
    t_cs(0); // 选中触摸IC

    /*发送命令*/
    for (uint8_t i = 0; i < 8; i++)
    {
        /*MCU向XTP2640发送数据*/
        t_sck(0);           // MCU准备数据
        if (command & 0x80) // 取最高位发送
        {
            t_mosi(1);
        }
        else
        {
            t_mosi(0);
        }
        delay_us(1); // MCU准备数据完成
        t_sck(1);    // MCU发送数据
        delay_us(1);

        command <<= 1;
    }

    /*过滤忙信号*/
    t_sck(0);
    delay_us(1);
    t_sck(1);
    delay_us(1);

    /*读取返回的数据*/
    for (uint8_t i = 0; i < 16; i++)
    {
        t_sck(0);
        delay_us(1);
        t_sck(1);

        data <<= 1;
        data |= t_miso();
        delay_us(1);
    }

    /*结束状态*/
    t_sck(0); // 完整周期
    t_cs(1);  // 释放片选

    return (data >> 4); // 取高12位是有效的
}

void t_calibration()
{
    double simple_kx = 240.0 / 4096;
    double simple_ky = 320.0 / 4096;
    const uint16_t x[5] = {120, 20, 220, 220, 20};
    const uint16_t y[5] = {160, 20, 20, 300, 300};
    uint16_t xl[5] = {0};
    uint16_t yl[5] = {0};

    for (uint8_t i = 0; i < 5; i++)
    {
        lcd_draw_cross(x[i], y[i], 19, 0xFFFF);
        while (1)
        {
            /*获取触摸屏原始数据*/
            uint16_t touch_x = 0;
            uint16_t touch_y = 0;
            touch_x = t_write_and_read_ad(0xD0);
            touch_y = t_write_and_read_ad(0x90);

            if (touch_x != 0 && touch_y != 4095)
            {
                xl[i] = touch_x;
                yl[i] = touch_y;
                // printf("touch_calibration_p%d:%d,%d\n", i, touch_x, touch_y);
                lcd_draw_cross(touch_x * simple_kx, touch_y * simple_ky, 19, 0xF800);
                HAL_Delay(500);
                break;
            }
        }
    }

    /*取出中心点的逻辑值和真实值*/
    xc = x[0];
    yc = y[0];
    xlc = xl[0];
    ylc = yl[0];

    /*计算校准参数*/
    linear_kx += xl[2] - xl[1];
    linear_kx += xl[3] - xl[4];
    linear_kx /= 2;
    linear_kx = (x[2] - x[1]) / linear_kx;

    linear_ky += yl[4] - yl[1];
    linear_ky += yl[3] - yl[2];
    linear_ky /= 2;
    linear_ky = (y[4] - y[1]) / linear_ky;

    printf("touch_calibration_result:%lf,%lf,%d,%d,%d,%d\n", linear_kx, linear_ky, xc, yc, xlc, ylc);
    lcd_clear(0x001F);
}

void t_get_position(uint16_t *x, uint16_t *y)
{
    /*获取触摸屏原始数据*/
    uint16_t touch_x = 0;
    uint16_t touch_y = 0;
    touch_x = t_write_and_read_ad(0xD0);
    touch_y = t_write_and_read_ad(0x90);

    /*通过校准参数校准*/
    *x = (touch_x - xlc) * linear_kx + xc;
    *y = (touch_y - ylc) * linear_ky + yc;
}

void t_set_calibration_value(double v0, double v1, uint16_t v2, uint16_t v3, uint16_t v4, uint16_t v5)
{
    linear_kx = v0;
    linear_ky = v1;
    xc = v2;
    yc = v3;
    xlc = v4;
    ylc = v5;
}
